package Ants.Model;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

public class Status {
	
		//Game config
	    public static int LoadTime;
	    public static int TurnTime;
	    public static int Turns;
	    public static int ViewRadius2;
	    public static int AttackRadius2;
	    public static int SpawnRadius2;
	    public static long Player_seed;
	    
	    public static Tile[][] Map;
	    public static int Rows;
	    public static int Cols;
	    
	    //Game status
	    private int turn;
	    private long startTurnTime;

		private LinkedList<Ant> allAnts = new LinkedList<Ant>();
		private LinkedList<Ant> myAnts = new LinkedList<Ant>();
		private LinkedList<Ant> enemiesAnts = new LinkedList<Ant>();
		private HashMap<Tile,Ant> movedAnts = new HashMap<Tile, Ant>();
		private LinkedList<Alert> alerts = new LinkedList<Alert>();
		private LinkedList<Tile> hills = new LinkedList<Tile>();
		private LinkedList<Tile> myHills = new LinkedList<Tile>();
		private LinkedList<Tile> enemiesHills = new LinkedList<Tile>();
		private LinkedList<Tile> foods = new LinkedList<Tile>();
		private HashMap<Tile,Integer> turnEnemiesTilesCounter = new HashMap<Tile,Integer>();

		private Status(){}
		
		private static Status istance = new Status();
		
		public static Status GetIstance(){
			return istance;
		}
		
		public void setup(List<String> data){
						
			for (String line : data) {
				String tokens[] = line.toLowerCase().split(" ");
				
				if (tokens[0].equals("loadtime")) {
					LoadTime = Integer.parseInt(tokens[1]);
				}
				else if (tokens[0].equals("turntime")) {
					TurnTime = Integer.parseInt(tokens[1]);
				}
				else if (tokens[0].equals("cols")) {
					Cols = Integer.parseInt(tokens[1]);		    	
				}
				else if (tokens[0].equals("rows")) {
					Rows = Integer.parseInt(tokens[1]);
				}
				else if (tokens[0].equals("turns")) {
					Turns = Integer.parseInt(tokens[1]);
				}
				else if (tokens[0].equals("viewradius2")) {
					ViewRadius2 = Integer.parseInt(tokens[1]);
				}
				else if (tokens[0].equals("attackradius2")) {
					AttackRadius2 = Integer.parseInt(tokens[1]);
				}
				else if (tokens[0].equals("spawnradius2")) {
					SpawnRadius2 = Integer.parseInt(tokens[1]);
				}
				else if (tokens[0].equals("player_seed")) {
					Player_seed = Long.parseLong(tokens[1]);
				}
			}
			
			Map = new Tile[Rows][Cols];
			for (int row = 0; row < Rows; row++) {
				Map[row] = new Tile[Cols];
				for (int col = 0; col < Cols; col++) {
					Map[row][col] = new Tile(row, col);
				}
			}
			
			for (int row = 0; row < Rows; row++) {
				for (int col = 0; col < Cols; col++) {
					Tile tile = Map[row][col];
					Tile n = Map[(row+Rows-1)%Rows][col];
					Tile e = Map[row][(col+1)%Cols];
					Tile s = Map[(row+1)%Rows][col];
					Tile w = Map[row][(col+Cols-1)%Cols];
					
					List<Tile> successors = new ArrayList<Tile>();
					successors.add(n);
					successors.add(e);
					successors.add(s);
					successors.add(w);
					
					tile.setSuccessors(successors);					
				}
			}
		}

		public void update(List<String> data){
			
			startTurnTime = System.currentTimeMillis();
			turn++;
			
			antsCleanUp();
			foodCleanUp();
			hillCleanUp();
			alertsCleanUp();
			
			for (String line : data) {
				String tokens[] = line.toLowerCase().split(" ");
				
				//ignora informazioni su turno, punteggio, ecc.
				if (tokens.length > 2) {
					int row = Integer.parseInt(tokens[1]);
					int col = Integer.parseInt(tokens[2]);
					Tile currentTile = Map[row][col];
					
					if (tokens[0].equals("a")){	
	
						Ant ant = new Ant(currentTile);
						ant.setTile(currentTile);
						ant.setId(Integer.parseInt(tokens[3]));
						currentTile.setAnt(ant);
						allAnts.add(ant);
						
						if(Integer.parseInt(tokens[3])==0){
							currentTile.setType(Type.MY_ANT);
							myAnts.add(ant);
						}
						else{
							currentTile.setType(Type.ENEMY_ANT);
							enemiesAnts.add(ant);
							
							Integer counter = turnEnemiesTilesCounter.get(currentTile);
							if(counter != null){
								counter++;
								turnEnemiesTilesCounter.put(currentTile, counter);
							}
							else
								 turnEnemiesTilesCounter.put(currentTile, 0);
						}
					}
					else if (tokens[0].equals("w")) {
						currentTile.setType(Type.WATER);
						for (Tile t : currentTile.getSuccessors())
							t.removeSuccessor(currentTile);
						currentTile.setSuccessors(new ArrayList<Tile>());
					}
					else if (tokens[0].equals("h")) {
						if(Integer.parseInt(tokens[3])==0){
							currentTile.setType(Type.MY_HILL);
							myHills.add(currentTile);
						}
						else{
							currentTile.setType(Type.ENEMY_HILL);
							enemiesHills.add(currentTile);
						}
						hills.add(currentTile);
					}
					else if (tokens[0].equals("f")) {
						currentTile.setType(Type.FOOD);
						foods.add(currentTile);
					}
				}
			}
			
			for (Tile t : turnEnemiesTilesCounter.keySet()){
				if(t.getType() != Type.ENEMY_ANT){
					turnEnemiesTilesCounter.put(t, -1);
				}
			}
		}

		public LinkedList<Ant> getAnts() {
			return allAnts;
		}

		public LinkedList<Tile> getHills() {
			return hills;
		}

		public LinkedList<Tile> getFoods() {
			return foods;
		}
		
	    public int getTurn() {
			return turn;
		}
	    
		private void antsCleanUp(){
			for (Ant ant : allAnts) {
				ant.getTile().setType(Type.LAND);
				ant.getTile().setAnt(null);
				ant.getTile().setChecked(false);
			}
			allAnts.clear();
			myAnts.clear();
			enemiesAnts.clear();
			movedAnts.clear();
		}

		private void foodCleanUp(){
			for (Tile food : foods){
				food.setType(Type.LAND);
				food.setChecked(false);
			}
			foods.clear();
		}
		
		private void hillCleanUp(){
			for (Tile hill : hills) {
				hill.setType(Type.LAND);
				hill.setChecked(false);
			}
			hills.clear();
			enemiesHills.clear();
		}

		private void alertsCleanUp(){
			for (Alert alert : alerts) {
				alert.setChecked(false);
			}
			alerts.clear();
		}
		
		public LinkedList<Ant> getMyAnts() {
			return myAnts;
		}

		public void setMyAnts(LinkedList<Ant> myAnts) {
			this.myAnts = myAnts;
		}
		
		public HashMap<Tile,Ant> getMovedAnts() {
			return movedAnts;
		}

		public void addMovedAnts(Tile oldTile, Ant ant) {
			movedAnts.put(oldTile, ant);
		}

		public LinkedList<Alert> getAlerts() {
			return alerts;
		}

		public void setAlerts(LinkedList<Alert> alerts) {
			this.alerts = alerts;
		}
		
		public LinkedList<Ant> getEnemiesAnts() {
			return enemiesAnts;
		}
		
		public LinkedList<Tile> getEnemiesHills() {
			return enemiesHills;
		}
		
		public LinkedList<Tile> getMyHills() {
			return myHills;
		}
		
		public HashMap<Tile, Integer> GetTurnEnmiesTilesCounter() {
			return turnEnemiesTilesCounter;
		}
		
		public long getStartTurnTime() {
			return startTurnTime;
		}
		
		public long getRemainingTime() {
			return TurnTime - (System.currentTimeMillis() - startTurnTime);
		}
}
